package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.IdAndNumDTO;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.trade.OrderBasicDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.po.PointsRecord;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.enums.PointsRecordType;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.mapper.PointsRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author Aimer
 * @since 2025-11-04
 */
@Service
@Slf4j
@RequiredArgsConstructor
@Transactional
public class LearningLessonServiceImpl extends
        ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {

    private final CourseClient courseClient;
    private final LearningLessonMapper learningLessonMapper;

    private final CatalogueClient catalogueClient;
    private final LearningRecordMapper learningRecordMapper;
    private final PointsRecordMapper pointsRecordMapper;
    @Override
    public void addLesson(OrderBasicDTO orderBasicDTO) {
        // 通过CourseClient获取课程信息集合
        List<CourseSimpleInfoDTO> courseInfoList = courseClient.getSimpleInfoList(orderBasicDTO.getCourseIds());
        // 判断获取到的集合是否有数据
        if (CollUtils.isEmpty(courseInfoList)){
            log.error("查询到的数据{}为空",courseInfoList);
            return;
        }
        List<LearningLesson> learningLessonList = new ArrayList<>(courseInfoList.size());
        for (CourseSimpleInfoDTO courseSimpleInfoDTO : courseInfoList) {
            LearningLesson learningLesson = new LearningLesson();
            // 获取过期时间
            if (courseSimpleInfoDTO.getValidDuration() != null && courseSimpleInfoDTO.getValidDuration() > 0){
                // 获取当前时间 + 课程失效时间 = 过期时间
                LocalDateTime now = LocalDateTime.now();
                learningLesson.setCreateTime(now);
                learningLesson.setExpireTime(now.plusMonths(courseSimpleInfoDTO.getValidDuration()));
            }
            log.info("用户id{}",orderBasicDTO.getUserId());
            learningLesson.setUserId(orderBasicDTO.getUserId());
            log.info("课程id{}",courseSimpleInfoDTO.getId());
            learningLesson.setCourseId(courseSimpleInfoDTO.getId());
            learningLessonList.add(learningLesson);
        }
        saveBatch(learningLessonList);
    }

    @Override
    public PageDTO<LearningLessonVO> getLearningLessonPage(PageQuery pageQuery) {
        // 获取当前登录用户id
        Long userId = UserContext.getUser();
        Page<LearningLesson> page = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .page(pageQuery.toMpPage("latest_learn_time", false));
        // 查看是否存在数据
        if (CollUtils.isEmpty(page.getRecords())){
            return PageDTO.empty(page);
        }
        List<LearningLesson> records = page.getRecords();
        Map<Long, CourseSimpleInfoDTO> longCourseSimpleInfoDTOMap = queryCourseSimpleInfoList(page.getRecords());
        List<LearningLessonVO> learningLessonVOS = new ArrayList<>(records.size());
        for (LearningLesson learningLesson : records) {
            LearningLessonVO learningLessonVO = BeanUtils.copyBean(learningLesson, LearningLessonVO.class);
            learningLessonVO.setCourseName(longCourseSimpleInfoDTOMap.get(learningLessonVO.getCourseId()).getName());
            learningLessonVO.setCourseCoverUrl(longCourseSimpleInfoDTOMap.get(learningLessonVO.getCourseId()).getCoverUrl());
            learningLessonVO.setSections(longCourseSimpleInfoDTOMap.get(learningLessonVO.getCourseId()).getSectionNum());
            learningLessonVOS.add(learningLessonVO);
        }
        return PageDTO.of(page,learningLessonVOS);
    }

    private Map<Long, CourseSimpleInfoDTO> queryCourseSimpleInfoList(List<LearningLesson> records) {
        // 3.1.获取课程id
        Set<Long> cIds = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toSet());
        // 3.2.查询课程信息
        List<CourseSimpleInfoDTO> cInfoList = courseClient.getSimpleInfoList(cIds);
        if (CollUtils.isEmpty(cInfoList)) {
            // 课程不存在，无法添加
            throw new BadRequestException("课程信息不存在！");
        }
        // 3.3.把课程集合处理成Map，key是courseId，值是course本身
        Map<Long, CourseSimpleInfoDTO> cMap = cInfoList.stream()
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
        return cMap;
    }

    @Override
    public void deleteLesson(Long userId,Long courseId) {
        // 根据用户id和课程id删除课表中的信息
        LambdaQueryWrapper<LearningLesson> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LearningLesson::getUserId,userId);
        lambdaQueryWrapper.eq(LearningLesson::getCourseId,courseId);
        remove(lambdaQueryWrapper);
    }

    @Override
    public Long isLessonValid(Long userId, Long courseId) {
        // 查询当前用户的课表下是否有该课程
        LambdaQueryWrapper<LearningLesson> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LearningLesson::getCourseId,courseId);
        lambdaQueryWrapper.eq(LearningLesson::getUserId,userId);
        LearningLesson learningLesson = getOne(lambdaQueryWrapper);
        if (learningLesson != null){
            return learningLesson.getId();
        }
        return 0L;
    }

    @Override
    public LearningLessonVO getUserLessonCourseStatus(Long userId, Long courseId) {
        // 查询当前用户的课表下是否有该课程
        LambdaQueryWrapper<LearningLesson> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LearningLesson::getCourseId,courseId);
        lambdaQueryWrapper.eq(LearningLesson::getUserId,userId);
        LearningLesson learningLesson = getOne(lambdaQueryWrapper);
        if (learningLesson == null){
            throw new RuntimeException("该用户的课程表中不存在该课程");
        }
        LearningLessonVO learningLessonVO = BeanUtils.copyBean(learningLesson, LearningLessonVO.class);
        return learningLessonVO;
    }

    @Override
    public Integer getCourseNumber(Long courseId) {
        LambdaQueryWrapper<LearningLesson> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LearningLesson::getCourseId,courseId);
        return count(lambdaQueryWrapper);
    }

    @Override
    public void createCourseStudyPlans(Long courseId, Integer freq) {
        // 获取当前登录用户id
        Long userId = UserContext.getUser();
        LambdaQueryWrapper<LearningLesson> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LearningLesson::getUserId,userId);
        lambdaQueryWrapper.eq(LearningLesson::getCourseId,courseId);
        LearningLesson learningLesson = getOne(lambdaQueryWrapper);
        // 查询课程是否存在
        if (learningLesson == null){
            throw new RuntimeException("课程不存在");
        }
        // 创建学习计划
        learningLesson.setWeekFreq(freq);
        if (learningLesson.getPlanStatus() == PlanStatus.NO_PLAN){
            learningLesson.setPlanStatus(PlanStatus.PLAN_RUNNING);
        }
        updateById(learningLesson);
    }

    @Override
    public LearningPlanPageVO queryMyPlans(PageQuery pageQuery) {
        LearningPlanPageVO result = new LearningPlanPageVO();
        // 获取当前登录用户id
        Long userId = UserContext.getUser();
        // 通过当前时间获取该星期的开始时间和结束时间
        LocalDate now = LocalDate.now();
        LocalDateTime start = DateUtils.getWeekBeginTime(now);
        LocalDateTime end = DateUtils.getWeekEndTime(now);

        // 3.查询总的统计数据
        // 3.1.本周总的已学习小节数量
        Integer weekFinished = learningRecordMapper.selectCount(new LambdaQueryWrapper<LearningRecord>()
                .eq(LearningRecord::getUserId, userId)
                .eq(LearningRecord::getFinished, true)
                .gt(LearningRecord::getFinished, start)
                .lt(LearningRecord::getFinished, end));
        result.setWeekFinished(weekFinished);

        // 3.2.本周总的计划学习小节数量
        Integer weekTotalPlan = learningLessonMapper.queryTotalPlan(userId);
        result.setWeekTotalPlan(weekTotalPlan);

        // 本周学习积分
        LambdaQueryWrapper<PointsRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(PointsRecord::getUserId,userId);
        lambdaQueryWrapper.between(PointsRecord::getCreateTime,start,end);
        lambdaQueryWrapper.eq(PointsRecord::getType, PointsRecordType.LEARNING);
        Integer points = pointsRecordMapper.queryUserPointsByTypeAndDate(lambdaQueryWrapper);
        result.setWeekPoints(points);
        // 查询分页数据
        // 4.1.分页查询课表信息以及学习计划信息
        Page<LearningLesson> page = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getStatus, PlanStatus.PLAN_RUNNING)
                .in(LearningLesson::getStatus, LessonStatus.NOT_BEGIN, LessonStatus.LEARNING)
                .page(pageQuery.toMpPage("latest_learn_time", false));
        List<LearningLesson> records = page.getRecords();
        if (CollUtils.isEmpty(records)){
            return new LearningPlanPageVO();
        }

        // 4.2.查询课表对应的课程信息
        Map<Long, CourseSimpleInfoDTO> cMap = queryCourseSimpleInfoList(records);
        // 4.3.统计每一个课程本周已学习小节数量
        List<IdAndNumDTO> list = learningRecordMapper.countLearnedSections(userId, start, end);
        Map<Long, Integer> countMap  = IdAndNumDTO.toMap(list);
        // 4.4.组装数据VO
        List<LearningPlanVO> voList = new ArrayList<>(records.size());
        for (LearningLesson r : records) {
            // 4.4.1.拷贝基础属性到vo
            LearningPlanVO vo = BeanUtils.copyBean(r, LearningPlanVO.class);
            // 4.4.2.填充课程详细信息
            CourseSimpleInfoDTO cInfo = cMap.get(r.getCourseId());
            if (cInfo != null) {
                vo.setCourseName(cInfo.getName());
                vo.setSections(cInfo.getSectionNum());
            }
            // 4.4.3.每个课程的本周已学习小节数量
            vo.setWeekLearnedSections(countMap.getOrDefault(r.getId(), 0));
            voList.add(vo);
        }
        return result.pageInfo(page.getTotal(), page.getPages(), voList);

    }

    @Override
    public LearningLessonVO queryMyCurrentLesson() {
        // 获取当前登录用户
        Long userId = UserContext.getUser();
        // 查询正在学习的课程
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .orderByDesc(LearningLesson::getLatestLearnTime)
                .last("limit 1")
                .one();
        if (lesson == null) {
            return null;
        }
        // 3.拷贝PO基础属性到VO
        LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);
        // 4.查询课程信息
        CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
        if (cInfo == null) {
            throw new BadRequestException("课程不存在");
        }
        vo.setCourseName(cInfo.getName());
        vo.setCourseCoverUrl(cInfo.getCoverUrl());
        vo.setSections(cInfo.getSectionNum());
        // 5.统计课表中的课程数量 select count(1) from xxx where user_id = #{userId}
        Integer courseAmount = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .count();
        vo.setCourseAmount(courseAmount);
        // 6.查询小节信息
        List<CataSimpleInfoDTO> cataInfos =
                catalogueClient.batchQueryCatalogue(CollUtils.singletonList(lesson.getLatestSectionId()));
        if (!CollUtils.isEmpty(cataInfos)) {
            CataSimpleInfoDTO cataInfo = cataInfos.get(0);
            vo.setLatestSectionName(cataInfo.getName());
            vo.setLatestSectionIndex(cataInfo.getCIndex());
        }
        return vo;
    }
}
